package core;

import core.PrefrenceLoader;
import encryption.Encrypter;
import encryption.EncryptionPlugin;
import network.Autodetect;
import network.NetworkingProtocol;
import network.Old_Client;
import network.Connection;
import network.DisconnectionException;
import network.Message;
import network.NetworkVars;
import network.NotACommandException;
import network.Peer;
import network.Proxy;
import network.Old_Server;
import network.Old_ServerThread;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import java.net.SocketTimeoutException;
import java.net.MulticastSocket;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Scanner;

import javax.swing.JOptionPane;
import javax.swing.UIManager;

import sun.audio.AudioPlayer;
import ui.Gui;
import ui.GuiPlugin;
import ui.IconLoader;
import ui.PopUp;
import ui.SoundPlayer;

public class Phrox {

	public static final String fD = System.getProperty("file.separator");
	public static final String os = System.getProperty("os.name").toLowerCase();
	public static final String rootDir = System.getProperty("user.dir");

	public static final String exitString ="/exit";//exit string
	public final static int PREFS_LENGTH = 5;

	//		major release.Minor release.Changes
	public static String name = "Phrox";
	public static final String versionMaj = "0.3";
	public static final String versionMin = "238";
	public static String version = versionMaj+"."+versionMin;

	private static boolean allowSpoof = false;

	private static UpdateEngine p_Update=null;//update engine
	private static Phrox phrox = null;

	public static boolean exit=false;//boolean to shut down the application
	public static boolean disconnect = false;//boolean for disconnecting, where application is not shut down.

	//the following two variables are for detecting lan Servers
	public static boolean broadcast=false;//broadcast ip to lan?
	public static boolean autoDetectLan=false;//listen to server ip broadcast? 

	//objects
	//*
	private Old_Client p_Client;
	private Old_Server p_Server;
	private Proxy p_Proxy;
	private static Peer p_peer;
	//*/

	//type of client/server
	//private int netType=-1;//type of thing to launch, client/server/etc...
	//	private boolean p_Protocol = true;//use protocol

	//other client stuff

	private static GuiPlugin plugin_Gui = null;//Custom gui?
	private static EncryptionPlugin plugin_Encryption = null;//encryption?
	private static boolean p_RemServer = false;//remember the server?

	//for sounds, like beeping.
	private static boolean sound_Mute=false;//true = muted, false = play sound
	private static boolean beep = false;
	private static SoundPlayer sound=null;
	private static String sound_file=null;


	public static void main(String[] args){
		
		//encryption
		boolean encrypt = false;
		int encryptType=0;
		String encryptPass="hi";

		//Client/Server + protocol
		int netType = -1;

		//update
		boolean update = false;

		//broadcasting
		boolean aLan = false;
		boolean bCast = false;

		//proxy
		//int proxyIn =54444;
		int proxyOut=54445;

		{



			for(String str : args){
				try{
					if(str.equalsIgnoreCase("client")){
						netType=0;
					}else if(str.equalsIgnoreCase("server")){
						netType=1;
					}else if(str.equalsIgnoreCase("proxy")){
						netType=2;
					}else if(str.contains("port=")){
						NetworkVars.socketNum = Integer.parseInt(str.substring(str.indexOf("=")+1));
						//this is the port that we will connect to, it is also used for auto detect
					}else if(str.contains("portopen=")){
						proxyOut = Integer.parseInt(str.substring(str.indexOf("=")+1));
						//this is the port that will be open for incomming connections
					}else if(str.contains("alias=")){
						NetworkVars.name = str.substring(str.indexOf("=")+1);
					}else if(str.contains("id=")){
						NetworkVars.localUsr.setName( str.substring(str.indexOf("=")+1) );
					}else if(str.contains("encrypt=")){
						encrypt=true;
						encryptType = Integer.parseInt(str.substring(str.indexOf("=")+1));
					}else if (str.contains("pass=")){
						encryptPass = str.substring(str.indexOf("=")+1);
					}else if(str.equalsIgnoreCase("broadcast")){
						// broadcast
						bCast = true;
					}else if(str.equalsIgnoreCase("autolan")){
						//auto detect lan
						aLan = true;

					}else if(str.equalsIgnoreCase("info")){
						System.out.println(p_Info());
						netType=-1;//this exits after command line arguments are read.
					}else if(str.equalsIgnoreCase("help")){
						//items are listed below in order of importance, opinion of programer
						System.out.println(p_Help());
						netType = -1;
					}else if(str.equalsIgnoreCase("update")){
						update = true;
					}else if(str.equalsIgnoreCase("gui")){

						//*
						try {
							UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
						}catch (Exception e1) {
							System.out.println("Unable to use System Look and Feel");
						}
						//doesn't really matter if any of the exceptions are thrown,
						//the default look and feel doesn't matter
						//*/

					}else if(str.equalsIgnoreCase("egg")){
						//TODO: easter egg
						System.out.println("                                ,_-=(!7(7/zs_.\n                             .='  ' .`/,/!(=)Zm.\n               .._,,._..  ,-`- `,\\ ` -` -`\\\\7//WW.\n          ,v=~/.-,-\\---!|V-s.)iT-|s|\\-.'   `///mK%.\n        v!`i!-.e]-g`bT/i(/[=.Z/m)K(YNYi..   /-]i44M.\n      v`/,`|v]-DvLcfZ/eV/iDLN\\D/ZK@%8W[Z..   `/d!Z8m\n     //,c\\(2(X/NYNY8]ZZ/bZd\\()/\\7WY%WKKW)   -'|(][%4.\n   ,\\\\i\\c(e)WX@WKKZKDKWMZ8(b5/ZK8]Z7%ffVM,   -.Y!bNMi\n   /-iit5N)KWG%%8%%%%W8%ZWM(8YZvD)XN(@.  [   \\]!/GXW[\n  / ))G8\\NMN%W%%%%%%%%%%8KK@WZKYK*ZG5KMi,-   vi[NZGM[\n i\\!(44Y8K%8%%%**~YZYZ@%%%%%4KWZ/PKN)ZDZ7   c=//WZK%!\n,\\v\\YtMZW8W%%f`,`.t/bNZZK%%W%%ZXb*K(K5DZ   -c\\\\/KM48\n-|c5PbM4DDW%f  v./c\\[tMY8W%PMW%D@KW)Gbf   -/(=ZZKM8[\n2(N8YXWK85@K   -'c|K4/KKK%@  V%@@WD8e~  .//ct)8ZK%8`\n=)b%]Nd)@KM[  !'\\c||Phrox||   !M@KZf    -c\\))ZDKW%`\nYYKWZGNM4/Pb  '-VscP4]b@W%     'Mf`   -L\\///KM(%W!\n!KKW4ZK/W7)Z. '/cttbY)DKW%     -`  .',\\v)K(5KW%%f\n'W)KWKZZg)Z2/,!/L(-DYYb54%  ,,`, -\\-/v(((KK5WW%f\n \\M4NDDKZZ(e!/\\7vNTtZd)8\\Mi!\\-,-/i-v((tKNGN%W%%\n 'M8M88(Zd))///((|D\\tDY\\\\KK-`/-i(=)KtNNN@W%%%@%[\n  !8%@KW5KKN4///s(\\Pd!ROBY8/=2(/4ZdzKD%K%%%M8@%%\n   '%%%W%dGNtPK(c\\/2\\[Z(ttNYZ2NZW8W8K%%%%YKM%M%%.\n     *%%W%GW5@/%!e]_tZdY()v)ZXMZW%W%%%*5Y]K%ZK%8[\n      '*%%%%8%8WK\\)[/ZmZ/Zi]!/M%%%%@f\\ \\Y/NNMK%%!\n        'VM%%%%W%WN5Z/Gt5/b)((cV@f`  - |cZbMKW%%|\n           'V*M%%%WZ/ZG\\t5((+)L\\'-,,/  -)X(NWW%%\n                `~`MZ/DZGNZG5(((\\,    ,t\\\\Z)KW%@\n                   'M8K%8GN8\\5(5///]i!v\\K)85W%%f\n                     YWWKKKKWZ8G54X/GGMeK@WM8%@\n                      !M8%8%48WG@KWYbW%WWW%%%@\n                        VM%WKWK%8K%%8WWWW%%%@`\n                          ~*%%%%%%W%%%%%%%@~\n                             ~*MM%%%%%%@f`\n                                  '''''");

					}else if(str.startsWith("/")){
						System.out.println("WARNING: Using special Dev code, may cause application instability.");
						//special dev code.
						//this is the format:"/"
						//delimit all things with commas
						/*
						 n:			name change
						 	Phrox.name
						 v:			version to pretend to be
						 	Phrox.version
						 d			debug
						 	NetworkVars.debug
						 net		show network io
						 	NetworkVars.showData
						 i			run 'install' method
						 	Phrox.install()
						 u			run 'uninstall' method
						 	Phrox.uninstall()
						 mc:		Maximum # of connections per server thread

						 */
						str = str.substring(1);
						System.out.println("=="+str+"==");
						String[] tmp = str.split(",");
						for(String s:tmp){
							if(s.equals("rem")){
								//really, we shouldn't tell ppl how to use these.
								System.out.println("n:'alpha'\tName change ( Phrox.name )\n" +
										"v:#.#.#\t\tVersion to be ( Phrox.version )\n" +
										"d\t\tDebug mode ( NetworkVars.debug )\n" +
										"net\t\tShow network IO( NetworkVars.showData )\n" +
										"i\t\tRun install method( Phrox.install() )\n" +
										"u\t\tRun uninstall Method ( Phrox.uninstall() )\n" +
										"mc:##\t\tMax # of connections per server thread\n" +
								"s\t\tAllow spoffing messages");
							}else if(s.startsWith("v:")){
								System.out.println("OVer:"+version);
								Phrox.version = s.substring(s.indexOf(":")+1);
								NetworkVars.name = name.toUpperCase()+"_"+version;
								System.out.println("Ver:"+version);
							}else if(s.startsWith("n:")){
								System.out.println("OName:"+name);
								Phrox.name = s.substring(s.indexOf(":")+1);
								NetworkVars.name = name.toUpperCase()+"_"+version;
								System.out.println("Name:"+name);
							}else if(s.equals("d")){
								NetworkVars.debug=true;
								System.out.println("DEBUG");
							}else if(s.equals("net")){
								NetworkVars.showData=true;
								System.out.println("SHOW DATA");
							}else if(s.equals("i")){
								System.out.println("RUN INSTALL");
								//install();
							}else if(s.equals("u")){
								System.out.println("Perminantly uninstalling Phrox.");
								unInstall();
							}else if(s.startsWith("mc:")){
								try {
									System.out.println("OMaxC:"+NetworkVars.MAX_CONNECTIONS);
									NetworkVars.MAX_CONNECTIONS = Integer.parseInt(s.substring(s.indexOf(":")+1));
									System.out.println("MaxC:"+NetworkVars.MAX_CONNECTIONS);
								} catch (NumberFormatException e) {
									System.out.println("Couldn't change max connections, parameter: NaN");
								}
							}else if(s.equals("s")){
								allowSpoof = true;
							}
						}

					}else if(str.equals("")){
						//do nothing

					}else{
						System.out.println("Error reading parameter\t\""+str+"\"");
					}
				} catch (Exception e) {
					e.printStackTrace();
					/*gobble exception, too bad can't set port*/
				}
			}

			if(netType == -1){
				System.exit(0);
			}

			System.out.println("--------");
			for(String str : args){
				System.out.println("cmd:"+str);
			}
			System.out.println("--------");
			//Mascot loader
			IconLoader mascotDisplay = new IconLoader(rootDir+fD+"res"+fD+"PhroxMascotSmall.JPG");
			long start = System.currentTimeMillis();

			System.out.println("--------");
			try {
				InetAddress b = InetAddress.getLocalHost();
				System.out.println("PCNAME:"+b.getCanonicalHostName()+"\nADDRESS:"+b.getHostAddress());
			} catch (UnknownHostException e1) {
				e1.printStackTrace();
			}
			System.out.println("--------");

			System.out.println("Checking for update...");

			try {
				buildUpdater();
				checkUpdate(false);

				if( p_Update.hasUpdate() &&( update || doUpdate()) ){
					//Theres an update and we want to update
					System.out.println("Auto Updating...");
					updatePhrox();
				}
			} catch (Exception e) {
				System.out.println("Update Failed:"+e.getMessage());
			}

			Thread hook = new Thread(){
				public void run(){
					if(plugin_Gui != null ){
						plugin_Gui.gui_display(false);
						plugin_Gui.gui_dispose();
					}
					System.out.println("Saving");
					phrox.save();
				}
			};

			Runtime.getRuntime().addShutdownHook(hook);

			System.out.println("--------");
			//initialize Phrox here.
			phrox = new Phrox(setupEncryption(encrypt,encryptType,encryptPass),proxyOut);

			System.out.println("--------");
			phrox.setup();
			System.out.println("--------");

			//*
			//end - start = total time taken to load. if it isn't 5 seconds, wait till 5 seconds.
			//long time = ();
			System.out.println("Load Time:"+(System.currentTimeMillis() - start)/1.0 +" ms");
			mascotDisplay.dispose();
			//*/
		}
		System.gc();
		phrox.setupName();
		do{

			phrox.start();
			System.gc();
			out("New Host? ");//TODO format text
		}while( !exit && netType != 1);


		System.exit(0);

	}



	public Phrox(EncryptionPlugin encryption){
		this(encryption, 54445);
	}

	/**
	 * @param type type of program.
	 * @param protocol use of protocol
	 * @param gui the class that the Gui will be built from.
	 * @param encryption encryption plugin to use.
	 * @param ProxyIn port in for proxy
	 * @param ProxyOut port out for proxy
	 * @param pl plugins to load.
	 */
	public Phrox(EncryptionPlugin encryption, int ProxyOut){
		//netType = type;

		plugin_Encryption = encryption;

		//proxy_portOut = ProxyOut;


	}


	public static void setup(){
		Object[] prefs = new Object[PREFS_LENGTH];
		prefs[0] = prefs [1] = null;
		prefs[2] = bCast;
		prefs[3] = aLan;
		prefs[4] = NetworkVars.socketNum;
		setupPrefs(prefs);


		setupGuiPlugin();
		setupSound();
		setupBroadcast();
		//setupName();//this should not be part of this method, as it requires user input
	}

	public static void setupSound(){
		sound = new SoundPlayer();
		//TODO check if user is using custom sound
		Thread s = new Thread(){
			public void run(){
				while(!exit){
					try {
						Thread.sleep(NetworkVars.defSleep);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					if(!sound_Mute && beep){
						//if not muted, and not already playing, and beep
						beep = false;
						sound.play("res"+fD+"beep_1.au",1000,2000);//TODO get beep + beep length
					}
				}
			}

		};
		System.out.println("Created Sound Thread");
		System.out.println("MUTE:"+sound_Mute);
		if (plugin_Gui != null) {
			//if there is a gui, then we beep on msg receive
			s.start();
		}			
	}

	public static void setupBroadcast(){
		if(p_peer == null){
			return;//not running
		}

		if( broadcast ){
			//setup server lan broadcast	
			Thread ipBroadcast = new Thread(){
				public void run(){
					if( p_peer.canBroadcast() && broadcast ){
						System.out.println("Broadcasting IP");
						String s;
						try {
							s = Phrox.os;
							if(s.contains("windows")){
								s = InetAddress.getLocalHost().getHostName();
							}else if(s.contains("linux")){
								s = InetAddress.getLocalHost().getHostName()+".local";
							}
							s = InetAddress.getByName(s).getHostAddress();
						} catch (UnknownHostException e) {
							s = "UNKNOWN";
							e.printStackTrace();
						}

						s = name +"_" + versionMaj +":" +s;
						Autodetect b = new Autodetect(2,s);
						while(!exit && broadcast && p_peer.canBroadcast()){//before exit, as long as server wants to broadcast

							if( b.receive(name+"_"+versionMaj +":REQ", NetworkVars.longSleep) ){
								boolean r = b.broadcast();
								if(!r){
									//broadcasting failed. abort.
									broadcast = false;
								}
	
							}
						}
						System.out.println("Stopped Broadcasting IP");
					}
				}
			};
			ipBroadcast.setDaemon(true);
			ipBroadcast.start();
		}


		if(autoDetectLan){
			Thread ipReceive = new Thread(){
				public void run(){
					String ret = getBroadcastedHosts();

					//wait until we know that the client wants the list.
					//at this point autoDetectLan will be set to false
					while (autoDetectLan) {
						try {
							Thread.sleep(NetworkVars.defSleep);
						} catch (InterruptedException e) {}
					}
					outln(ret);

				}
			} ;

			ipReceive.setDaemon(true);
			ipReceive.start();
		}

	}

	public static String getBroadcastedHosts(){
		return Autodetect.getBroadcastedHosts(name+"_"+versionMaj,':',name+"_"+versionMaj +":REQ");
	}

	public void start(){
		if(plugin_Gui != null){
			plugin_Gui.gui_display(true);
		}

		System.out.println("--------");

		if(netType == 1){



			try {
				outln(p_Server.serverCommands("/info"));
			} catch (NotACommandException e1) {
				//won't happen, this is hard coded...so programmer should know better!
			}

			//*
			Thread server = new Thread(){
				public void run(){

					String str = "";
					while(!exit){
						str = user_GetText(false);
						try {
							String out=null;
							if(str.length() > 0 && str.charAt(0) == '/'){
								if(str.equals(exitString)){
									break;
								}
								try {
									out = p_Server.serverCommands(str);
								} catch (NotACommandException e) {
									e.printStackTrace();
									outln("Error processing command.");
									out = null;
								}
							}
							if(out == null){
								Message m = new Message(Message.TEXT_MSG, NetworkVars.localUsr.getName()+": "+str);
								p_Server.sendAll(m);
							}else if(out.length() < 3){

							}else{
								outln(out);
							}

						} catch (Exception e) {
							//This loop is not allowed to fail.
							e.printStackTrace();
						}
					}
					//outln("Server shut down in 5 seconds.");
					p_Server.sendAll(Old_Server.SERVER_CLOSE);
					if(p_Server.numConnection() != 0){
						try {
							Thread.sleep(5000);
						} catch (InterruptedException e) {}
					}

					p_Server.close();
					exit = true;
					try {
						Thread.sleep(p_Server.numConnection()*500);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}

					System.exit(0);
				}
			};

			//*/

			//server


			server.setDaemon(true);
			server.start();
			p_Server.startServer();


		}else if(netType == 2){
			//Proxy thread
			//*
			Thread proxy = new Thread(){
				public void run(){
					while (!exit) {
						Scanner scan = new Scanner(System.in);
						String in = "";
						while (!in.equals(exitString) && !exit && !disconnect) {
							in = scan.nextLine();
							p_Proxy.command(in);
						}
						p_Proxy.close();
						exit = true;
					}
				}
			};

			//*/

			//proxy
			//proxy.setDaemon(false);

			try {
				Scanner s = new Scanner(System.in);
				System.out.println("="+getBroadcastedHosts());//TODO find out why this doesn't work.
				System.out.println("Server? (Ip or URL)");
				p_Proxy.changeHost( InetAddress.getByName(s.nextLine()) );
			} catch (UnknownHostException e) {
				e.printStackTrace();
			}
			if(proxy.getState().ordinal() != 1){
				proxy.start();
			}
			p_Proxy.run();


			//*

			//*/
		}else{//if (netType ==0 )


			//Client thread
			try {
				InetAddress tmp = getHost();
				p_Client.setHost(tmp);
				p_Client.prepConnect();
				disconnect = false;
			} catch (UnknownHostException e1) {
				e1.printStackTrace();
				System.err.println("ERROR couldn't create client");
				System.exit(1);
			}

			if( exit ){
				return;
			}

			//*
			Thread client = new Thread("Client Thread"){
				public void run(){
					//CORE.SCPnoPS.outln("Started");
					while (!exit) {//while we don't exit app
						while (p_Client.getConStat() != 1) {
							try {
								Thread.sleep(100);
							} catch (InterruptedException e) {}
						}
						//for some reason client gets stuck here...
						//plugin_Gui.chat_ClearText();
						String str = " ";
						while (!exit && !disconnect) {
							str = user_GetText(true);
							//System.out.println(this.getState().ordinal()+":ooO0");
							try {
								if ( str.length() > 0 && str.charAt(0) == '/') {
									if (isLocalCommand(str)) {
										String temp = p_Client.clientCommands(str);
										if (temp.length() > 0) {
											Phrox.outln(temp);
										}
									} else if (str.equals(exitString)) {
										exit = true;
										break;
									} else {
										Message m = new Message(Message.REQUEST_MSG, str);
										p_Client.send(m);
									}
								} else if (str.length() > 0){
									p_Client.sendText(str);
								}
							} catch (NotACommandException e) {
								//not a command, shouldn't exit because of this
								displayln("Not a command:" + e.getMessage());
							} catch (Exception e) {
								p_Client.disconnect();
								e.printStackTrace();
								disconnect = true;
							}

						}
						hasLag((byte)-1);
						//System.exit(0);
					}
					exit = true;
					p_Client.disconnect();

				}


			};
			//*/

			//client

			client.setDaemon(true);
			if(client.getState().ordinal() != 1){
				System.out.println("Start CLIENT");
				client.start();
			}
			p_Client.run();
			p_Client.prepConnect();//need to call this incase we want to start a new connection

		}
	}


	/**
	 * This method builds an updater that can check for updates. Uses UpdateEngine class.
	 */
	private static void buildUpdater() {

		String in ="http://code.google.com/p/phroxchat";//all phorx downloads
		String reg ="http.{0,50}?Phrox_v[\\d\\.]*.zip";//WORKS FOR PHROX CHAT
		String noHttpReg ="Phrox_v[\\d\\.]*.zip";
		//httpLoc, remReg, curVer, String locReg, int minlen, boolean updateFolder){
		p_Update = new UpdateEngine(in,reg,(name+"_v"+version+".zip"),noHttpReg,10,false);

	}



	/**
	 * Load user prefrences.
	 */
	private static Object[] loadPrefs() {
		Object[] prefs = new Object[PREFS_LENGTH];

		try {
			IO.openInputFile("res"+fD+"Prefs.data");
			String in="";

			while((in = IO.readLine()) != null){

				try {
					if(in.contains("MUTE:")){
						prefs[0] = Boolean.parseBoolean(in.substring(in.indexOf(":")+1));
					}else if(in.contains("SERVERPOLICY:")){
						prefs[1] = Boolean.parseBoolean(in.substring(in.indexOf(":")+1));
					}else if(in.contains("BROADCAST:")){
						prefs[2] = Boolean.parseBoolean(in.substring(in.indexOf(":")+1));
					}else if(in.contains("PORT:")){
						prefs[3] = Integer.parseInt(in.substring(in.indexOf(":")+1));
					}else if(in.contains("PORTOPEN:")){
						prefs[4] = Integer.parseInt(in.substring(in.indexOf(":")+1));
					}
				} catch (Exception e) {
					//Exception parsing boolean
					e.printStackTrace();
				}

			}
			IO.closeInputFile();
		} catch (Exception e) {

			e.printStackTrace();
		}
		return prefs;
	}

	private static Object[] defaultPrefs(){
		Object[] prefs = new Object[PREFS_LENGTH];
		prefs[0] = beep;
		prefs[1] = p_RemServer;
		prefs[2] = broadcast;
		prefs[3] = autoDetectLan;
		prefs[4] = NetworkVars.socketNum;
		return prefs;
	}

	private static void setupPrefs(Object[] o){
		System.out.println("Loading Prefrences...");
		/*
		 * Preferences to use:
		 * Broadcast
		 * Beep sound
		 * Mute sound
		 * remember last server
		 * last server
		 * auto update
		 * gui plugin
		 * encryption plugin
		 * allow incoming
		 * incoming port
		 * username
		 * 
		 * 
		 */

		Object[] prefs = loadPrefs();
		Object[] defPrefs = defaultPrefs();
		try {
			prefs = PrefrenceLoader.setupPrefs(prefs, defPrefs, o, PREFS_LENGTH);

			beep = (Boolean)prefs[0];
			p_RemServer = (Boolean)prefs[1];
			broadcast = (Boolean)prefs[2];
			autoDetectLan = (Boolean)prefs[3];
			NetworkVars.socketNum = (Integer)prefs[4];
		} catch (Exception e) {

		}

		System.out.println("Current Prefrences:");
		System.out.println("MUTE SOUND: "+beep);
		System.out.println("REM_SERVER: "+p_RemServer);
		System.out.println("BROADCAST: "+broadcast);
		System.out.println("AUTOLAN: "+autoDetectLan);
		System.out.println("PORT: "+NetworkVars.socketNum);
	}


	private static boolean doUpdate() {

		try {
			IO.openInputFile("res"+fD+"Prefs.data");
			String in="";
			while(in != null){
				in = IO.readLine();
				if(in.contains("UPDATEPOLICY:")){
					return Boolean.parseBoolean(in.substring(in.indexOf(":")+1));
				}
			}
			IO.closeInputFile();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}



	/**
	 * This method loads the encryption file named in the Prefs.data file, by the ENCRYPTION: attribute
	 * @return returns the Encryption Plugin object to be used.
	 */
	private static EncryptionPlugin loadEncryptionPlugin(){



		//THIS LOADS A NEW Encryption plugin FROM OUTSIDE

		EncryptionPlugin modInstance=null;

		try {


			File prefs = new File("res"+fD+"Prefs.data");
			IO.openInputFile(prefs.getAbsolutePath());

			String path=null;
			String in;
			while ((in = IO.readLine()) != null) {

				if(in.contains("ENCRYPTION:")){
					path = in.substring(in.indexOf(":")+1);
					break;
				}

			}
			IO.closeInputFile();

			//System.out.println(path);

			File dir = new File(""+path+".class");
			System.out.println("ENCRYPTIONPLUGIN:"+dir.getAbsolutePath());
			if(!dir.exists()){//gui file doesn't exist, return null as custom gui.
				return null;
			}
			URL loadPath = dir.toURI().toURL();

			URL[] classUrl = new URL[]{loadPath};

			ClassLoader cl = new URLClassLoader(classUrl);

			Class loadedClass = cl.loadClass(path);

			modInstance = (EncryptionPlugin)loadedClass.newInstance();


		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			if(modInstance != null){
				return modInstance;
			}
		}

		return null;

	}


	private static EncryptionPlugin setupEncryption(boolean b, int type, String pass){
		if(!b){
			return null;
		}
		EncryptionPlugin ret = null;

		ret = loadEncryptionPlugin();
		//load custom Encryption
		if(ret == null){//if there is a custom encryption, don't create the default
			ret = new Encrypter();
		}
		ret.setPassword(pass);
		ret.setMethod(type);
		return ret;
	}


	/**
	 * This method loads the Gui Plugin that is named in the Prefs.data file, by GUI:
	 * @return returns the Class of the Gui Plugin to be used.
	 */
	private static Class loadGuiPlugin(){
		//THIS LOADS A NEW GUI FROM OUTSIDE
		try {
			File prefs = new File("res"+fD+"Prefs.data");
			IO.openInputFile(prefs.getAbsolutePath());

			String path=null;
			String in;
			while ((in = IO.readLine()) != null) {

				if(in.contains("GUI:")){
					path = in.substring(in.indexOf(":")+1);
					break;
				}

			}
			IO.closeInputFile();

			//System.out.println(path);

			File dir = new File(""+path+".class");
			System.out.println("GUI_FILE:"+dir.getAbsolutePath());
			if(!dir.exists()){//gui file doesn't exist, return null as custom gui.
				return null;
			}
			URL loadPath = dir.toURI().toURL();

			URL[] classUrl = new URL[]{loadPath};

			ClassLoader cl = new URLClassLoader(classUrl);

			Class loadedClass = cl.loadClass(path);
			System.out.println("GUI:"+loadedClass.getCanonicalName());
			return loadedClass;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}


	/**
	 * Initialises the gui
	 */
	private static void setupGuiPlugin(){


		Thread guiWatch = new Thread(){
			/*
			 * This thread checks the gui periodically to see if
			 * it still exists, and is useable. if it is, then 
			 * the exit variable is set to false (program continues),
			 * other wise, it is set to true. (program exits)
			 * 
			 */
			public void run(){
				if(plugin_Gui != null){
					while(!exit){
						exit = !plugin_Gui.gui_displayable();
						try {
							Thread.sleep(250);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			}
		};

		guiWatch.setDaemon(true);


		//as long as it isn't a file share, or proxy create teh gui
		try {
			plugin_Gui = (GuiPlugin) loadGuiPlugin().newInstance();//load custom gui,
		} catch (Exception e1) {
			plugin_Gui = null;
		}
		if(plugin_Gui == null){//if there is a custom gui, don't create the default
			plugin_Gui = new Gui(name+" "+version+"");
		}else{
			plugin_Gui.gui_setTitle(name+" "+version+"");
		}

		guiWatch.start();
	}


	/**
	 * Sets up the nickname of the user
	 */
	private void setupName(){
		if(plugin_Gui != null){
			System.out.println("Changing name...");
			//if a server, nopserver, proxy, or file transfer then id == SERVER
			boolean valid = false;
			while(!valid){
				String temp = JOptionPane.showInputDialog("Your current nickname is: "+NetworkVars.localUsr.getName()+", leave this field blank to keep it. Or type in a new one to change it.");
				if(temp != null && (temp.length() < 2 || temp.charAt(0) == '/')){
					temp = "";
					ui.PopUp.showPopUp(Phrox.name,"Names can contain only numbers and\nletters. It must also be atleast 3\ncharacters.");
				}else if(temp == null){
					valid = true;
				}else{
					valid =true;
					NetworkVars.localUsr.setName(temp);
				}
			}
			plugin_Gui.chat_ClearText();
			plugin_Gui.chat_AddText("You are now known as:"+NetworkVars.localUsr.getName()+"\n");
		}
		if(plugin_Gui != null){
			plugin_Gui.userName_SetText("You are: "+NetworkVars.localUsr.getName());
		}

		System.out.println("USERNAME:"+NetworkVars.localUsr.getName());
	}


	private void loadBanned(){
		try {

			System.out.println("Loading Ban list");

			IO.openInputFile("res"+fD+"Banned.data");

			ArrayList<InetAddress> b= new ArrayList<InetAddress>();
			String str = "";
			while( (str=IO.readLine()) != null ){
				try {
					b.add(InetAddress.getByName(str));
					System.out.println(str);
				} catch (UnknownHostException e) {}
			}
			IO.closeInputFile();

			for(InetAddress inet : b){
				p_Server.ban(inet);
			}

			System.out.println("Ban list loaded\n--------");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch(IOException e){
			e.printStackTrace();
		}
	}

	private InetAddress getHost() throws UnknownHostException{
		//if auto detect

		autoDetectLan = false;//make sure it is false
		//this is the trigger for the ip receiving thread to show where the hosts are

		try {
			//wait to make sure the hosts get displayed
			Thread.sleep(NetworkVars.defSleep*2);
		} catch (InterruptedException e) {}

		outln("Enter Host: (IP or URL)");
		if(plugin_Gui != null){
			plugin_Gui.type_SetText(lastHost());
		}
		InetAddress host = null;
		String str ="";
		do{
			try {
				str = user_GetText(false);
				host = InetAddress.getByName(str);
			} catch (Exception e) {
				outln("Error: '"+str+"' is not a valid host.");
				outln("Enter Host name: ");
			}
		}while( null == host );
		return host;
	} 

	/**
	 * This method only works as long as "dns" doesn't resolve to a domain.
	 * @return hopefully returns the IP of the DNS servers used by the user 
	 *
	 * @throws UnknownHostException if the host name is not legal.
	 * */
	private InetAddress getDNS() throws UnknownHostException{
		return InetAddress.getByName("dns");
	}

	/**
	 * Saves the last server, if wanted. Resaves server/update policy as well as gui location.
	 */
	private void save(){

		try {
			IO.openInputFile("res"+fD+"Prefs.data");
			String in="";
			boolean uP = false;//update policy
			//auto update?
			String others ="";
			while((in = IO.readLine()) != null){

				if(in.contains("UPDATEPOLICY:")){
					in = in.substring(in.indexOf(":")+1);
					uP = Boolean.parseBoolean(in);
				}else if(in.contains("GUI:")){
					others += in.replace("\n", "").concat("\n");
				}else if(in.contains("ENCRYPTION:")){
					others += in.replace("\n", "").concat("\n");
				}else if(in.contains("BROADCAST:")){
					others += in.replace("\n", "").concat("\n");
				}else if(in.contains("AUTOLAN:")){
					others += in.replace("\n", "").concat("\n");
				}
			}
			IO.closeInputFile();


			String save = "";
			if(p_Client != null){
				if(p_RemServer){
					System.out.println("Saving host");
					save += "SERVER:" + p_Client.getHost().getHostAddress() + "\n";
				}
				IO.createOutputFile("res"+fD+"Info.data");
				IO.println(save);
				IO.closeOutputFile();

			}else if(p_Server != null){
				System.out.println("Saving ban list");
				//save banned list
				ArrayList<InetAddress> b=p_Server.getBanned();

				IO.createOutputFile("res"+fD+"Banned.data");

				for(InetAddress inet : b){
					System.out.println(inet.getHostAddress());
					IO.println(inet.getHostAddress());
				}
				IO.closeOutputFile();

			}



			IO.createOutputFile("res"+fD+"Prefs.data");
			for(String s : others.split("\n")){
				IO.println(s);
			}
			if(!others.contains("ENCRYPTION:")){
				IO.println("ENCRYPTION:");
			}
			if(!others.contains("GUI:")){
				IO.println("GUI:");
			}
			if(!others.contains("BROADCAST:")){
				IO.println("BROADCAST:"+broadcast);
			}
			if(!others.contains("AUTOLAN:")){
				IO.println("AUTOLAN:"+autoDetectLan);
			}
			IO.println("PORT:"+NetworkVars.socketNum);

			IO.println("MUTE:"+sound_Mute);
			IO.println("SERVERPOLICY:"+p_RemServer);
			IO.println("UPDATEPOLICY:"+uP);
			IO.closeOutputFile();

		} catch (Exception e) {
			e.printStackTrace();
		}

	}



	public static String p_Help(){
		String ret = "";
		ret += ("Options:\n");

		ret += ("client\t\t\tstarts client\n");
		ret += ("server\t\t\tstarts server\n");
		ret += ("proxy\t\t\tstarts proxy\n");
		ret += "\tIf none of the above are used, client is default\n";
		ret += ("update\t\t\twill check for an update\n");
		ret += ("=server, proxy\n" +
		"\toptions disables name changing, name is auto: SERVER\n");


		ret += ("*port=xxxx\t\tsets port for server connection\n");

		ret += ("portopen=xxxx\t\tsets port that proxy will open for a connecting client\n");

		ret += ("encrypt=xxx\t\tencrypts the connection, where xxx is encryption type\n"+
				"\t\tthere are "+(Encrypter.MAX_ENCRYPTION_TYPE+1)+" different encryption types chose one to use.\n" +
				"\t\tmake sure both the client, and server use the same type.\n" +
				"\t\tenrcyption numbres start @ 0 and go to "+Encrypter.MAX_ENCRYPTION_TYPE+"\n" +
		"\t\tNOTE: encrypt doesn't work with proxy\n");

		ret += ("pass=\t\t\tpick your password for encrypt, not nessisary\n" +
		"\t\tbut will change from the default\n");

		ret += ("file=\t\t\tpick the file to be transfered, (C:\\... or /home/... format)\n");

		ret += "*autolan\t\tAuto detects servers running on the lan\n";

		ret += "*broadcast\t\tAs server, add this so you broadcast yourself to others\n";

		ret += ("alias=\t\t\tchose what the program checks for as connection password\n" +
		"\t\tAlias isn't exaclty a password, but important none the less.\n");

		ret += ("id=\t\t\tchose your start id, instead of reading it from file.\n");


		ret += ("info\t\t\tdisplays programmer info, program info, etc...\n");

		ret += ("help\t\t\tdisplays this\n");

		ret += "gui\t\t\tAttempt to use system drawn GUI\n" +
		"\t\tMight slow down Phrox\n";

		/*
		ret += ("install\t\t\tbuilds files to launch diffrent aspects of the program\n" +
				"\t.bat for windows\n" +
				"\t.sh for linux\n" +
				"\t.command for mac\n");
		 */

		ret += "Everything marked with a * is a saved prefrence.\n";
		return ret;
	}
	/*
	//Commented out install() because newer version shouldn't use this.

	private static boolean install(){

		{
			File dir = new File("res"+fD);
			if(!dir.exists() && dir.mkdir()){
				System.out.println("Resource directory created.");
			}
		}

		String name = os;
		String instName = name+".jar";
		String ext = "";
		try {
			if(name.contains("windows")){//Windows OS
				ext = "bat";
				//normal
				IO.createOutputFile("Server."+ext);
				IO.println("net view");
				IO.println("pause");
				IO.println("java -jar "+instName+" server port=54444");
				IO.println("pause");
				IO.closeOutputFile();

				IO.createOutputFile("Client."+ext);
				IO.println("java -jar "+instName+" client port=54444");
				IO.closeOutputFile();

				IO.createOutputFile("Info."+ext);
				IO.print("java -jar "+instName+" info");
				IO.closeOutputFile();	

				IO.createOutputFile("Help."+ext);
				IO.print("java -jar "+instName+" help");
				IO.println("pause");
				IO.closeOutputFile();

				IO.createOutputFile("Proxy."+ext);
				IO.print("java -jar "+instName+" proxy portin=54444 portout=54445");
				IO.println("pause");
				IO.closeOutputFile();

				IO.createOutputFile("ClientWProxy."+ext);
				IO.print("java -jar "+instName+" client port=54445");
				IO.closeOutputFile();

				//encrypted:
				// encrypt=1
				// pass=hi

				IO.createOutputFile("EServer."+ext);
				IO.println("net view");
				IO.println("pause");
				IO.print("java -jar "+instName+" server port=54444 encrypt=1 pass=hi");
				IO.println("pause");
				IO.closeOutputFile();

				IO.createOutputFile("EClient."+ext);
				IO.print("java -jar "+instName+" client port=54444 encrypt=1 pass=hi");
				IO.closeOutputFile();

				IO.createOutputFile("EClientWProxy."+ext);
				IO.print("java -jar "+instName+" client port=54445 encrypt=1 pass=hi");
				IO.closeOutputFile();


			}else if(name.contains("linux")){//how to detect Linux?
				ext = "sh";
				IO.createOutputFile("Server."+ext);
				IO.println("#!/bin/bash");
				IO.println("java -jar "+instName+" server port=54444");
				IO.closeOutputFile();


				IO.createOutputFile("Client."+ext);
				IO.println("#!/bin/bash");
				IO.println("java -jar "+instName+" client port=54444");
				IO.closeOutputFile();

				IO.createOutputFile("Info."+ext);
				IO.println("#!/bin/bash");
				IO.print("java -jar "+instName+" info");
				IO.closeOutputFile();	

				IO.createOutputFile("Help."+ext);
				IO.println("#!/bin/bash");
				IO.print("java -jar "+instName+" help");
				IO.println("pause");
				IO.closeOutputFile();

				IO.createOutputFile("Proxy."+ext);
				IO.println("#!/bin/bash");
				IO.print("java -jar "+instName+" proxy portin=54444 portout=54445");
				IO.println("pause");
				IO.closeOutputFile();

				IO.createOutputFile("ClientWProxy."+ext);
				IO.println("#!/bin/bash");
				IO.print("java -jar "+instName+" client port=54445");
				IO.closeOutputFile();

				//encrypted:
				// encrypt=1
				// pass=hi

				IO.createOutputFile("EServer."+ext);
				IO.println("#!/bin/bash");
				//IO.println("net view");
				//IO.println("pause");
				IO.print("java -jar "+instName+" server port=54444 encrypt=1 pass=hi");
				IO.println("pause");
				IO.closeOutputFile();

				IO.createOutputFile("EClient."+ext);
				IO.println("#!/bin/bash");
				IO.print("java -jar "+instName+" client port=54444 encrypt=1 pass=hi");
				IO.closeOutputFile();

				IO.createOutputFile("EClientWProxy."+ext);
				IO.println("#!/bin/bash");
				IO.print("java -jar "+instName+" client port=54445 encrypt=1 pass=hi");
				IO.closeOutputFile();

			}else if(name.contains("mac")){//Mac?
				ext = "command";
				//file ext is .command
				//include "#!/bin/sh" as first line.


				IO.createOutputFile("Server."+ext);
				IO.println("#!/bin/sh");
				IO.println("java -jar "+instName+" server port=54444");
				IO.closeOutputFile();


				IO.createOutputFile("Client."+ext);
				IO.println("#!/bin/sh");
				IO.println("java -jar "+instName+" client port=54444");
				IO.closeOutputFile();

				IO.createOutputFile("Info."+ext);
				IO.println("#!/bin/sh");
				IO.print("java -jar "+instName+" info");
				IO.closeOutputFile();	

				IO.createOutputFile("Help."+ext);
				IO.println("#!/bin/sh");
				IO.print("java -jar "+instName+" help");
				IO.println("pause");
				IO.closeOutputFile();

				IO.createOutputFile("Proxy."+ext);
				IO.println("#!/bin/sh");
				IO.print("java -jar "+instName+" proxy portin=54444 portout=54445");
				IO.println("pause");
				IO.closeOutputFile();

				IO.createOutputFile("ClientWProxy."+ext);
				IO.println("#!/bin/sh");
				IO.print("java -jar "+instName+" client port=54445");
				IO.closeOutputFile();

				//encrypted:
				// encrypt=1
				// pass=hi

				IO.createOutputFile("EServer."+ext);
				IO.println("#!/bin/sh");
				//IO.println("net view");
				//IO.println("pause");
				IO.print("java -jar "+instName+" server port=54444 encrypt=1 pass=hi");
				IO.println("pause");
				IO.closeOutputFile();

				IO.createOutputFile("EClient."+ext);
				IO.println("#!/bin/sh");
				IO.print("java -jar "+instName+" client port=54444 encrypt=1 pass=hi");
				IO.closeOutputFile();

				IO.createOutputFile("EClientWProxy."+ext);
				IO.println("#!/bin/sh");
				IO.print("java -jar "+instName+" client port=54445 encrypt=1 pass=hi");
				IO.closeOutputFile();

			}else{//don't know what the OS is.
				return false;
			}

			IO.createOutputFile("res"+fD+"install.data");
			IO.println("Client."+ext);
			IO.println("Info."+ext);
			IO.println("Help."+ext);
			IO.println("Proxy."+ext);
			IO.println("ClientWProxy."+ext);
			IO.println("EServer."+ext);
			IO.println("EClient."+ext);
			IO.println("EClientWProxy."+ext);
			IO.println("res"+fD+"Banned.data");
			IO.println("res"+fD+"beep_1.au");
			IO.println("res"+fD+"Info.data");
			IO.println("res"+fD+"PhroxThumb.JPG");
			IO.println("res"+fD+"Prefs.data");
			IO.println("res"+fD+"PhroxMascotSmall.JPG");
			IO.closeOutputFile();

		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	*/

	/**
	 * This method will not return, unless it fails.
	 * It will queue the Phrox.jar file for deletion,
	 *  and delete all files associated to the program.
	 * @return
	 */
	private static boolean unInstall(){
		File list = new File("res"+fD+"install.data");
		ArrayList<String> files = new ArrayList<String>();
		if(list.exists()){
			try {
				IO.openInputFile("res"+fD+"install.data");
				while(true){
					String s = IO.readLine();
					if(s==null){
						break;
					}
					files.add(s);
				}
				IO.closeInputFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		for(String s : files){
			File f = new File(s);
			if(!f.exists()){
				continue;
			}
			if(!f.delete()){
				System.out.println(f.getAbsolutePath()+" was not deleted.");
			}
		}

		File f = new File(name+".jar");
		f.deleteOnExit();
		System.exit(0);
		return false;
	}


	private String user_GetText(boolean dis){
		String ret = null;
		while(!exit){

			if(dis && disconnect){
				break;
			}

			if(plugin_Gui.type_hasText()){

				ret = plugin_Gui.type_GetText();
			}

			if(ret != null && ret.replace(" ", "").replace("\t", "").replace("\n", "").length()>0){
				return ret;
			}else{
				ret =null;
			}

			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

		}
		return "";
	}


	private static void updatePhrox(){
		if(p_Update == null){
			return;
		}
		if(p_Update.update()){//if it updates
			//show the user a message, then quit.
			JOptionPane.showMessageDialog(null, "Phrox has updated succesfully.\nPlease extract files from "+p_Update.getFile()+", and restart.");
			System.exit(0);
		}
	}


	public boolean hasExited(){
		return exit;
	}

	public static String p_Info(){
		String ret = "";

		ret += (name + "\tv" + version + "\n");

		ret += ("Programmers:\n"+
				"\tGianni Gambetti" + "\n");

		ret += ("Testers:\n" +
				"\tGianni Gambetti\n" +
				"\tClaudio Gambetti\n" +
				"\tMartin Klemes\n" +
				"\tMike Lee\n" +
				"\tChris Burke\n" +
				"\tWilliam Dodsworth\n" +
				"\tJay-tee Brown" +
		"\n");

		ret += ("Art team:\n" +
		"\tSarah Benning - Mascot\n");

		ret += "Default Beep:\n"
			+"\thttp://simplythebest.net\n";

		ret += ("Contact:\n" +
				"\tgianni_judo@hotmail.com" + "\n");
		return ret;
	}


	public static String p_ShortInfo(){
		String ret = "";

		ret += (name + "\t v" + version + "\n");
		ret += ("Curently hosted on:\n");
		ret += (" http://code.google.com/p/phroxchat\n");
		ret += ("Contact:\n");
		ret += (" gianni_judo@hotmail.com");

		return ret;
	}


	/**
	 * Checks to see if there is an updated Phrox.
	 * <br>
	 * This will update Phrox if the user clicks yes on
	 * the "update?" message.
	 * @param boolean true if you want to show the "No update" popup
	 */
	public static void checkUpdate(boolean showOther){

		if(p_Update == null){
			return;
		}

		if(p_Update.checkForUpdate()){
			System.out.println("Update available.");
			System.out.println("Current Ver:"+name+" "+version);
			System.out.println("Update:"+p_Update.getFile());
			//String[] options ={"NO","YES"};
			int i = JOptionPane.showOptionDialog(null, "Phrox has found a new version, update?",
					"Phrox updater", JOptionPane.YES_NO_OPTION , JOptionPane.QUESTION_MESSAGE,
					null, null, null);
			if(NetworkVars.debug){
				System.out.println("Update box value:"+i);
				//TODO i think this part works diffrently on diffrent OSs
			}
			if( i == 0){

				Phrox.updatePhrox();
			}

		}else{
			System.out.println("No update.");
			if(showOther){
				JOptionPane.showMessageDialog(null, "No updates for Phrox at this time.");
			}
		}
	}



	/**
	 * Plays the generic beep
	 */
	public static void beep(){
		beep = true;
	}




	/**
	 * @return returns in String format, the IP address of the last host connected to.
	 */
	public String lastHost(){
		//load last server.

		try {
			IO.openInputFile("res"+fD+"Info.data");
			String in="";
			while((in = IO.readLine()) != null){

				if(in.contains("SERVER:")){
					return in.substring(in.indexOf(":")+1);
				}

			}

			IO.closeInputFile();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";

	}

	//*
	public String commands(String str) throws NotACommandException{
		String ret = "";
		str = str.toLowerCase().trim();
		if(str.length()>0)
			if(str.charAt(0) == '/'){
				if(str.contains("/time")){

					long total = System.currentTimeMillis()/1000 - p_peer.getStartTime();

					byte minutes = (byte) ((total/60)%60);
					byte hours = (byte) ((total/3600)%24);
					int days = (int) (total/86400);
					ret="Run Time: d"+days+" h"+hours+" m"+minutes;
					System.out.println(ret);

				}else if(str.equals("/beep")){
					beep = true;
				}else if(str.startsWith("/spoof") && Phrox.allowSpoof){

					String[] cm = str.split(" ");

					if(str.length() <= 7 || cm.length < 4){
						ret = "usage: /spoof (#) (msg) (ip/user to send to)" +
						"where number is one of:" +
						"\t0 Connection Msg\n" +
						"\t2 PingS\n" +
						"\t3 PingR\n" +
						"\t4 Keep Alive\n" +
						"\t5 S Redund\n" +
						"\t6 Redund\n" +
						"\t7 Info\n" +
						"USE THIS CAREFULLY.";
					}else{

						try {
							byte num  = Byte.parseByte( cm[1] );
							Message m = new Message( num, cm[2] );
							Connection c = p_peer.getUser( cm[3] );
							if( c != null){
								p_peer.send(m, c );
								ret = "Sent: "+num+" "+cm[2]+" to "+cm[3];
							}else{
								ret = "Couldn't find user: "+cm[3];
							}
						} catch (NumberFormatException e) {
							ret = "Couldn't parse type: "+cm[1];
						}
					}

				}else if(str.equals("/detect")){
					ret = getBroadcastedHosts();
				}else if(str.contains("/ping")){

					String command;
					try {
						command = str.substring(str.indexOf(" ")+1).trim();
					} catch (Exception e) {
						command = "";
					}
					if(command.equals("all")){
						//ping all users :)
						for(Connection c : clients){
							System.out.println("Pinging:"+c.user.getIp()+"");
							Message pi = new Message(Message.PINGS,System.currentTimeMillis()+"");
							try {
								Old_ServerThread.send(c,pi);
							} catch (DisconnectionException e) {}
						}
					}else{
						if(p_peer.getServer().getIp().getHostAddress().contains(command)){
							System.out.println("Pinging:"+p_peer.getServer().getName()+p_peer.getServer().getIp()+"");
							Message pi = new Message(Message.PINGS,System.currentTimeMillis()+"");
							send(pi,serv);
						}else{
							for(Connection c : clients){
								if(c.user.getIp().getHostAddress().contains(command)){
									System.out.println("Pinging:"+c.user.getName()+c.user.getIp()+"");
									Message pi = new Message(Message.PINGS,System.currentTimeMillis()+"");
									send(pi,c);
									break;
								}
							}
						}
					}
				}else if(str.startsWith("/con")){
					String command;
					String ip = "";
					String port = "";
					try {
						command = str.substring(str.indexOf(" ")+1).trim();
						ip = command.substring(0,command.indexOf(":"));
						port = command.substring(command.indexOf(":")+1);
					} catch (Exception e) {
						command = "";
					}
					if(serv.connectionStatus == -1){
						//then we queue connecting to 'ip' at 'port'
					}
					return commands("/redund s");
				}else if(str.startsWith("/sredund")){
					return commands("/redund s");
				}else if(str.startsWith("/redund")){
					//Print the redundant connection for us
					String command;
					try {
						command = str.substring(str.indexOf(" ")+1).trim();
					} catch (Exception e) {
						command = "";
					}
					String[] list = null;
					if( command.equals("s") ){
						list = p_peer.getRedundS();
					}else{
						list = p_peer.getRedund();
					}
					ret += "Redundant Servers";
					for(String s : list){
						byte[] b = core.Util.getBytes(s);
						int p = (int)core.Util.add(b[4], b[5]);
						ret += b[0] +"."+b[1]+"."+b[2]+"."+b[3]+":"+p+"\n";
					}

				}else if(str.equals("/members")){
					//print a list of all members connected to us
					ret += NetworkVars.Msg_Format+"/-Members-\\";
					ret += NetworkVars.Msg_Format+serv.user.getIp()+":"+serv.user.getName()+"\n";
					for(Connection c : clients){
						ret += NetworkVars.Msg_Format+c.user.getIp()+":"+c.user.getName()+"\n";
					}
					ret += NetworkVars.Msg_Format+"\\---------/";

				}else if(str.contains("/help")){
					ret ="Commands for the server are:\n" +
					"/beep\t\tbeeps like it would for message received\n" +
					"/members\t\tprints a list of all members connected to us\n" +
					"/time\t\tshows uptime\n" +
					"/cls\t\tclears the text area\n" +
					"/info\t\tdisplays external IP and version info";
				}else if(str.equalsIgnoreCase("/cls")){
					Phrox.gui_ClearText();
				}else if(str.equals("/info")){
					String s;
					try {
						s = Phrox.os;
						if(s.contains("windows")){
							s = InetAddress.getLocalHost().getHostName();
						}else if(s.contains("linux")){
							s = InetAddress.getLocalHost().getHostName()+".local";
						}
						s = InetAddress.getByName(s).getHostAddress();
					} catch (UnknownHostException e) {
						s = "UNKNOWN";
						e.printStackTrace();
					}
					ret = "External IP: "+ Phrox.getIP() +"\n" +
					"Lan IP: "+s+"\n"+
					"Version: "+Phrox.version+"\n" +
					"Name: "+Phrox.name+"\n"+
					"Port: "+NetworkVars.socketNum;
				}else{
					ret = null;
				}
			}
		if(ret == null){
			throw new NotACommandException(""+str);
		}
		if(NetworkVars.debug){
			System.out.println("========\n"+ret+"\n========");
		}
		return ret;


	}
	//*/

	public static void displayln(String str){
		display(str+"\n");
	}

	public static void display(String str){
		if(plugin_Gui != null){
			plugin_Gui.chat_AddText(str);
			beep();
		}
	}


	public static String getIP(){
		String ret = "";
		try {
			String url = "http://www.whatismyip.com/automation/n09230945.asp";
			URL test1 = new URL(url);
			URLConnection con1 = test1.openConnection();
			con1.setReadTimeout(3000);//3 second time out.
			InputStreamReader stream1 = new InputStreamReader(con1.getInputStream());
			BufferedReader read1 = new BufferedReader(stream1);
			while(true){

				String a = read1.readLine();

				if (a == null){
					break;
				}
				ret = ret + a;

			}
			read1.close();
			stream1.close();

		} catch (Exception e) {
			//problem retreiving ip...
		}
		return ret;
	}




	public static void gui_ClearText(){
		plugin_Gui.chat_ClearText();
	}

	public static void gui_changeName(){
		plugin_Gui.userName_SetText("You are: "+NetworkVars.localUsr.getName());
	}

	public static void out(String str){
		display(str);
	}

	public static void outln(String str){
		displayln(str);
	}

	public static void hasLag(byte b){
		plugin_Gui.gui_hasLag(b);
	}

	/**
	 * Sets mute value for Phrox
	 * @param b true to mute sound, false to restore sound
	 */
	public static void setSoundMute(boolean b){
		sound_Mute = b;
	}

	public static boolean getMute(){
		return sound_Mute;
	}

	/**
	 * 
	 * @return returns wether or not remembering the server is set.
	 */
	public static boolean getRemServer(){
		//System.out.println("PHROX REM_SERVER:"+p_RemServer);
		return phrox.p_RemServer;
	}

	/**
	 * @param b value to change p_RemServer to.
	 */
	public static void setRemServer(boolean b){
		phrox.p_RemServer = b;
	}


}
